﻿#include "playhand.h"

PlayHand::PlayHand() {}

PlayHand::PlayHand(Cards &cards) {
  // 1. 对扑克牌进行分类: 1张的, 2张, 3张, 4张有多少种
  classify(cards);
  // 2. 对牌型进行分类
  judgeCardType();
}

PlayHand::PlayHand(HandType type, Card::CardPoint pt, int extra) {
  m_type = type;
  m_pt = pt;
  m_extra = extra;
}

void PlayHand::classify(Cards &cards) {
  CardList list = cards.toCardList();
  int cardRecord[Card::Card_End];  //点数枚举最大值（点数 隐式转 int）
  memset(cardRecord, 0, sizeof(int) * Card::Card_End);

  for (int i = 0; i < list.size(); ++i) {
    Card c = list.at(i);
    cardRecord[c.point()]++;  //对应点数的牌个数加一
  }
  //清空牌组容器，准备写入
  m_oneCard.clear();
  m_twoCard.clear();
  m_threeCard.clear();
  m_fourCard.clear();

  for (int i = 0; i < Card::Card_End; ++i) {
    if (cardRecord[i] == 1)  //判断个数
    {
      m_oneCard.push_back(
          (Card::CardPoint)i);  //加入牌组，强转枚举（int->点数）
    } else if (cardRecord[i] == 2) {
      m_twoCard.push_back((Card::CardPoint)i);
    } else if (cardRecord[i] == 3) {
      m_threeCard.push_back((Card::CardPoint)i);
    } else if (cardRecord[i] == 4) {
      m_fourCard.push_back((Card::CardPoint)i);
    }
  }
}

void PlayHand::judgeCardType() {
  m_type = Hand_Unknown;
  m_pt = Card::Card_Begin;
  m_extra = 0;  //记录牌数

  if (isPass()) {
    m_type = Hand_Pass;
  }
  if (isSingle()) {
    m_type = Hand_Single;  //单牌
    m_pt = m_oneCard[0];   //点数
  } else if (isPair()) {
    m_type = Hand_Pair;   //双牌
    m_pt = m_twoCard[0];  //点数
  } else if (isTriple()) {
    m_type = Hand_Triple;   //三牌
    m_pt = m_threeCard[0];  //点数
  } else if (isTripleSingle()) {
    m_type = Hand_Triple_Single;  //三带一
    m_pt = m_threeCard[0];        //点数
  } else if (isTriplePair()) {
    m_type = Hand_Triple_Pair;  //三带二
    m_pt = m_threeCard[0];
  } else if (isPlane()) {
    m_type = Hand_Plane;  //飞机
    // 记录点数最小的牌
    m_pt = m_threeCard[0];  // 0位是最小牌，用数组判断牌型时从小到大判断
  } else if (isPlaneTwoSingle()) {
    m_type = Hand_Plane_Two_Single;
    // 记录点数最小的牌
    m_pt = m_threeCard[0];
  } else if (isPlaneTwoPair()) {
    m_type = Hand_Plane_Two_Pair;
    // 记录点数最小的牌
    m_pt = m_threeCard[0];
  } else if (isSeqPair()) {
    m_type = Hand_Seq_Pair;  //连对
    // 记录点数最小的牌
    m_pt = m_twoCard[0];
    m_extra = m_twoCard.size();  //对数（有几个对）
  } else if (isSeqSingle()) {
    m_type = Hand_Seq_Single;  //连对
    // 记录点数最小的牌
    m_pt = m_oneCard[0];
    m_extra = m_oneCard.size();
  } else if (isBomb()) {
    m_type = Hand_Bomb;  //炸弹
    // 记录点数最小的牌
    m_pt = m_fourCard[0];
  } else if (isBombSingle()) {
    m_type = Hand_Bomb_Single;
    // 记录点数最小的牌
    m_pt = m_fourCard[0];
  } else if (isBombPair()) {
    m_type = Hand_Bomb_Pair;
    // 记录点数最小的牌
    m_pt = m_fourCard[0];
  } else if (isBombTwoSingle()) {
    m_type = Hand_Bomb_Two_Single;
    // 记录点数最小的牌
    m_pt = m_fourCard[0];
  } else if (isBombJokers()) {
    m_type = Hand_Bomb_Jokers;
  } else if (isBombJokersSingle()) {
    m_type = Hand_Bomb_Jokers_Single;  //王炸
  } else if (isBombJokersPair()) {
    m_type = Hand_Bomb_Jokers_Pair;
  } else if (isBombJokersTwoSingle()) {
    m_type = Hand_Bomb_Jokers_Two_Single;
  }
}

bool PlayHand::isPass() {
  if (m_oneCard.size() == 0 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    return true;
  }
  return false;
}

PlayHand::HandType PlayHand::getHandType() { return m_type; }

Card::CardPoint PlayHand::getCardPoint() { return m_pt; }

int PlayHand::getExtra() { return m_extra; }

bool PlayHand::canBeat(const PlayHand &other) {
  // 我的牌型是未知的
  if (m_type == Hand_Unknown) {
    return false;
  }
  // 对方放弃出牌
  if (other.m_type == Hand_Pass) {
    return true;
  }
  // 我是王炸
  if (m_type == Hand_Bomb_Jokers) {
    return true;
  }
  if (m_type == Hand_Bomb && other.m_type >= Hand_Single &&
      other.m_type <= Hand_Seq_Single) {
    return true;
  }
  // 双方的牌型一致
  if (m_type == other.m_type) {
    if (m_type == Hand_Seq_Pair || m_type == Hand_Seq_Single) {
      return m_pt > other.m_pt && m_extra == other.m_extra;
    } else {
      return m_pt > other.m_pt;
    }
  }
  return false;
}

bool PlayHand::isSingle() {
  if (m_oneCard.size() == 1 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    return true;
  }
  return false;
}

bool PlayHand::isPair() {
  if (m_oneCard.isEmpty() && m_twoCard.size() == 1 && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    return true;
  }
  return false;
}

bool PlayHand::isTriple() {
  if (m_oneCard.isEmpty() && m_twoCard.isEmpty() && m_threeCard.size() == 1 &&
      m_fourCard.isEmpty()) {
    return true;
  }
  return false;
}

bool PlayHand::isTripleSingle() {
  if (m_oneCard.size() == 1 && m_twoCard.isEmpty() && m_threeCard.size() == 1 &&
      m_fourCard.isEmpty()) {
    return true;
  }
  return false;
}

bool PlayHand::isTriplePair() {
  if (m_oneCard.isEmpty() && m_twoCard.size() == 1 && m_threeCard.size() == 1 &&
      m_fourCard.isEmpty()) {
    return true;
  }
  return false;
}

bool PlayHand::isPlane() {
  if (m_oneCard.isEmpty() && m_twoCard.isEmpty() && m_threeCard.size() == 2 &&
      m_fourCard.isEmpty()) {
    std::sort(m_threeCard.begin(), m_threeCard.end());
    if (m_threeCard[1] - m_threeCard[0] == 1 && m_threeCard[1] < Card::Card_2) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isPlaneTwoSingle() {
  if (m_oneCard.size() == 2 && m_twoCard.isEmpty() && m_threeCard.size() == 2 &&
      m_fourCard.isEmpty()) {
    std::sort(m_threeCard.begin(), m_threeCard.end());
    std::sort(m_oneCard.begin(), m_oneCard.end());
    if (m_threeCard[1] - m_threeCard[0] == 1 && m_threeCard[1] < Card::Card_2 &&
        m_oneCard[0] != Card::Card_SJ && m_oneCard[1] != Card::Card_BJ) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isPlaneTwoPair() {
  if (m_oneCard.isEmpty() && m_twoCard.size() == 2 && m_threeCard.size() == 2 &&
      m_fourCard.isEmpty()) {
    std::sort(m_threeCard.begin(), m_threeCard.end());
    if (m_threeCard[1] - m_threeCard[0] == 1 && m_threeCard[1] < Card::Card_2) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isSeqPair() {
  if (m_oneCard.isEmpty() && m_twoCard.size() >= 3 && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    std::sort(m_twoCard.begin(), m_twoCard.end());
    if (m_twoCard.last() - m_twoCard.first() == (m_twoCard.size() - 1) &&
        m_twoCard.first() >= Card::Card_3 && m_twoCard.last() < Card::Card_2) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isSeqSingle() {
  if (m_oneCard.size() >= 5 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    std::sort(m_oneCard.begin(), m_oneCard.end());
    if (m_oneCard.last() - m_oneCard.first() == (m_oneCard.size() - 1) &&
        m_oneCard.first() >= Card::Card_3 && m_oneCard.last() < Card::Card_2) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isBomb() {
  if (m_oneCard.isEmpty() && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.size() == 1) {
    return true;
  }
  return false;
}

bool PlayHand::isBombSingle() {
  if (m_oneCard.size() == 1 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.size() == 1) {
    return true;
  }
  return false;
}

bool PlayHand::isBombPair() {
  if (m_oneCard.isEmpty() && m_twoCard.size() == 1 && m_threeCard.isEmpty() &&
      m_fourCard.size() == 1) {
    return true;
  }
  return false;
}

bool PlayHand::isBombTwoSingle() {
  if (m_oneCard.size() == 2 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.size() == 1) {
    std::sort(m_oneCard.begin(), m_oneCard.end());
    if (m_oneCard.first() != Card::Card_SJ &&
        m_oneCard.last() != Card::Card_BJ) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isBombJokers() {
  if (m_oneCard.size() == 2 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    std::sort(m_oneCard.begin(), m_oneCard.end());
    if (m_oneCard.first() == Card::Card_SJ &&
        m_oneCard.last() == Card::Card_BJ) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isBombJokersSingle() {
  if (m_oneCard.size() == 3 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    std::sort(m_oneCard.begin(), m_oneCard.end());
    if (m_oneCard[1] == Card::Card_SJ && m_oneCard[2] == Card::Card_BJ) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isBombJokersPair() {
  if (m_oneCard.size() == 2 && m_twoCard.size() == 1 && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    std::sort(m_oneCard.begin(), m_oneCard.end());
    if (m_oneCard[0] == Card::Card_SJ && m_oneCard[1] == Card::Card_BJ) {
      return true;
    }
  }
  return false;
}

bool PlayHand::isBombJokersTwoSingle() {
  if (m_oneCard.size() == 4 && m_twoCard.isEmpty() && m_threeCard.isEmpty() &&
      m_fourCard.isEmpty()) {
    std::sort(m_oneCard.begin(), m_oneCard.end());
    if (m_oneCard[2] == Card::Card_SJ && m_oneCard[3] == Card::Card_BJ) {
      return true;
    }
  }
  return false;
}
